package controller;

import java.util.ArrayList;
import java.util.List;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import utilities.AssertionAnalyser;
import utilities.Scan;


/**
 * 
 * @author lsajeev
 * 
 */
public class AssertionAnalysisController {
	private static final Logger LOG = LoggerFactory
			.getLogger(AssertionAnalysisController.class);
	private Scan scan = new Scan();

	public AssertionAnalysisController() {
		// no args
	}

	/**
	 * print list of assertions
	 * 
	 * @param doc
	 * @param po
	 * @throws XPathExpressionException
	 */
	/**
	 * Finds assertions with more than one pattern to match and prints them 
	 * @param doc
	 * @param po
	 * @return
	 * @throws XPathExpressionException
	 */
	
	//assertionList, 
	public boolean printAssertions(Document doc )
			throws XPathExpressionException {
		boolean isValid = true;

		List<Element> assertionList = new ArrayList<Element>();
		assertionList = AssertionAnalyser.findMultipleAssertionPatterns(doc);
		System.out.println("  *********************  Results of the Assertion Analysis *******************");

		//iterate through the assertion list 
		//if assertion list greater than zero get assertion name
		for (int index = 0; index < assertionList.size(); index++) {
			if (0 <= assertionList.size()) {
				Element assertion = assertionList.get(index);

				String assertionName = assertion.getAttribute("testname");
				isValid = true;

				// attributes
				System.out.println();
				System.out.println(index + 1 + "  AssertionName  :  " + assertionName);
				//list of nodes to match
				XPath path = XPathFactory.newInstance().newXPath();
				NodeList patterns = (NodeList) path.evaluate(
						"./collectionProp/stringProp", assertion,
						XPathConstants.NODESET);

				System.out.println("   Patterns to Match : " + patterns.getLength());
			} else {
				isValid = false;
			}

		}
		return isValid;
	}

	/**
	 * gets user input and returns a list of nodes to alter
	 * 
	 * @param po
	 * @return
	 */
	public List<Element> nodesToAlter(Document doc) {
		List<Element> list = new ArrayList<Element>();
		
		list  = AssertionAnalyser.findMultipleAssertionPatterns(doc);
		
		
		ArrayList<Integer> intList = new ArrayList<Integer>();
		List<Element> returnList = new ArrayList<Element>(); // list for assertion
														// analyzer
		
		if (0 == list.size()) {
			System.out.println("No assertions have more than one pattern.  ");
		} else {

			intList = (ArrayList<Integer>) userInput(list.size()); // user's input
		}
		printToScreen(list, intList);
		// iterate through user input
		for (int j = 0; j < intList.size(); j++) {
			int tempA = intList.get(j);
			returnList.add(list.get(tempA - 1));
		}
		return returnList;
	}

	/**
	 * Prints list of nodes to screen
	 * 
	 * @param list
	 * @param intList
	 * @return
	 */
	protected boolean printToScreen(List<Element> list,
			List<Integer> intList) {
		// iterate through list of elements and print 
		for (int q = 0; q < list.size(); q++) {
			System.out.println(list.get(q).getNodeName());
		}

		return true;

	}

	/**
	 * Will get user input and parse through it and return an arrayList of Integers
	 * 
	 * @return
	 */
	public List<Integer> userInput(int maxSize) {

		boolean isValid = true;
		ArrayList<Integer> returnList = null;

		do {
			ArrayList<Integer> intList = new ArrayList<Integer>(); // list for
																	// user
			isValid = true; // input
			System.out.println();

			String input = scan.getUserInput("Enter numbers to be altered :");
			input = input + ",";
			String[] userInput = input.split(",");

			for (String value : userInput) {

				// using Integer.parseInt
				try {
					int temp = Integer.parseInt(value);
					intList.add(temp);
				} catch (NumberFormatException e) {
					System.out.println(value + " is not a valid number");
					isValid = false;
					LOG.error("*** NumberFormatException***");
				}
			}
			for (int index : intList) {
				if (maxSize < index || 1 > index ) {
					isValid = false;
				}
			}

			if (isValid) {
				returnList = intList;
			} else {
				System.out.println("Please enter a valid response.  ");
			}
		} while (!isValid);

		return returnList;

	}

	/**
	 * getter and setter for scan for testing
	 * 
	 * @return
	 */
	public Scan getScan() {
		return scan;
	}

	public void setScan(Scan scan) {
		this.scan = scan;
	}
}
